#include "ProgressDialog.h"
#include "ui_sign_scan_state.h"

#include <QDebug>
#include <QMessageBox>

#include "SearchController/SearchController.h"

ProgressDialog::ProgressDialog(QWidget *parent, const QString & path, bool bFileType, IConfig *config)
    : QDialog(parent)
    , ui(new Ui::sign_scan_state)
    , m_searchType(bFileType ? ESearchTypeFile : ESearchTypeFolder)
    , m_searchPath(path)
    , m_searchController(NULL)
    , m_Statistics()
    , m_config(config)
{
    m_searchController = new SearchController(this, config);

    connect(m_searchController, SIGNAL(sigProgress(float)), this, SLOT(onProgress(float)));
    connect(m_searchController, SIGNAL(sigFoundGUID(QString, QString)), this, SLOT(onFoundGUID(QString, QString)));
    connect(m_searchController, SIGNAL(sigNotFoundGUID(QString)), this, SLOT(onNotFoundGUID(QString)));
    connect(m_searchController, SIGNAL(sigError(QString, QString)), this, SLOT(onError(QString, QString)));
    connect(m_searchController, SIGNAL(sigInterrupted()), this, SLOT(onInterrupted()));
    connect(m_searchController, SIGNAL(finished ()), SLOT(onComplete()));

    ui->setupUi(this);
}

ProgressDialog::ProgressDialog(QWidget *parent, const QByteArray & byteArray, IConfig *config)
    : QDialog(parent)
    , ui(new Ui::sign_scan_state)
    , m_searchType(ESearchTypeByteArray)
    , m_searchController(NULL)
    , m_byteArray(byteArray)
    , m_Statistics()
    , m_config(config)
{
    m_searchController = new SearchController(this, config);
    connect(m_searchController, SIGNAL(sigProgress(float)), this, SLOT(onProgress(float)));
    connect(m_searchController, SIGNAL(sigFoundGUID(QString, QString)), this, SLOT(onFoundGUID(QString, QString)));
    connect(m_searchController, SIGNAL(sigNotFoundGUID(QString)), this, SLOT(onNotFoundGUID(QString)));
    connect(m_searchController, SIGNAL(sigError(QString, QString)), this, SLOT(onError(QString, QString)));
    connect(m_searchController, SIGNAL(sigInterrupted()), this, SLOT(onInterrupted()));
    connect(m_searchController, SIGNAL(finished ()), SLOT(onComplete()));

    ui->setupUi(this);
}

ProgressDialog::~ProgressDialog()
{
    delete ui;
}

void ProgressDialog::done(int r)
{
    if (confirmCancelScan())
    {
        m_searchController->interrupt();
        return;
    }

    QDialog::done(r);
}


void ProgressDialog::show()
{
    // Run the scan processing
    switch (m_searchType)
    {
    case    ESearchTypeFile:
        m_searchController->scanFile(m_searchPath);
        break;
    case    ESearchTypeFolder:
        m_searchController->scanFolder(m_searchPath);
        break;
    case    ESearchTypeByteArray:
        m_searchController->scanByteArray(m_byteArray);
        break;
    }

    printLog("Scan process is started...");
    ui->progressBar->setValue(100);
    QDialog::show();

}

void ProgressDialog::on_cancel_clicked()
{
    if (confirmCancelScan())
        m_searchController->interrupt();
}

void ProgressDialog::onProgress(float progressValue)
{
    int absProgressValuePerProcent = int(progressValue * 1000);
    if (ui->progressBar->value() < absProgressValuePerProcent)
        ui->progressBar->setValue(absProgressValuePerProcent);
}

void ProgressDialog::onFoundGUID(QString fileName, QString guid)
{
    ++m_Statistics.total;
    ++m_Statistics.infected;

    if (fileName.isEmpty())
        printLog(QString("Byte array is infected GUID= %1").arg(guid));
    else
        printLog(QString("Object \"%1\" is infected GUID= %2").arg(fileName, guid));

}

void ProgressDialog::onNotFoundGUID(QString /* fileName */)
{
    ++m_Statistics.total;
}

void ProgressDialog::onError(QString fileName, QString errMessage)
{
    ++m_Statistics.total;

    if (fileName.isEmpty())
        printLog(QString("error: %1").arg(errMessage));
    else
        printLog(QString("Object \"%1\" scanning is failed. Error: %2").arg(fileName, errMessage));
}

void ProgressDialog::onInterrupted()
{
    m_Statistics.canceled = true;
    ++m_Statistics.total;
}

void ProgressDialog::onComplete()
{
    onProgress(1);

    printLog("-------------------------");
    if (m_Statistics.canceled)
        printLog("Scan process is completed");
    else
        printLog("Scan process is canceled");
    printLog(QString().sprintf("Total objects: %d", m_Statistics.total));
    printLog(QString().sprintf("Infected: %d", m_Statistics.infected));
    printLog(QString().sprintf("Errors: %d", m_Statistics.errors));
}

void ProgressDialog::printLog(QString printText, QColor textColor)
{
    QString logText = ui->log->toPlainText();

    if (!logText.isEmpty() && !printText.isEmpty()) logText += "\n";
    ui->log->setPlainText(logText + printText);

    QTextEdit::ExtraSelection selection;
    QTextCursor cursor = QTextCursor(ui->log->document());
    cursor.movePosition(QTextCursor::Start);
    cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
    cursor.select(QTextCursor::LineUnderCursor);

    QTextCharFormat format;
    format.setForeground(textColor);
    selection.cursor = cursor;
    selection.format = format;
    ui->log->setExtraSelections(QList<QTextEdit::ExtraSelection>() << selection);

    cursor = ui->log->textCursor();
    cursor.movePosition(QTextCursor::End);
    ui->log->setTextCursor(cursor);
    ui->log->ensureCursorVisible();
}

bool ProgressDialog::confirmCancelScan()
{
    if (m_searchController->isRunning())
    {
        QMessageBox message;

        message.setIcon(QMessageBox::Question);
        message.setWindowTitle("Signatures Detector");
        message.setText("Do you really wants to cancel scan process?");

        message.addButton(tr("&Yes"), QMessageBox::AcceptRole);
        message.addButton(tr("&No"), QMessageBox::RejectRole);

        message.exec();
        return (message.result() == QMessageBox::AcceptRole);
    }

    return false;
}



